Skip to main content
Version: 0.6.0

Top APIs in the Untold Engine

Quick Reference

CategoryCommon APIs
EntitiescreateEntity, destroyEntity, setParent, findEntity
TransformsgetLocalPosition, getPosition, getLocalOrientation, getOrientation, getForwardAxisVector, translateTo, translateBy, rotateTo, rotateBy
AssetsassetBasePath
RenderingsetEntityMesh, setEntityGaussian, createDirLight, createPointLight, createSpotLight, createAreaLight
AnimationsetEntityAnimations, changeAnimation, pauseAnimationComponent
PhysicssetEntityKinetics, setMass, setGravityScale, applyForce, steerTo, steerAway, steerPursuit, followPath
ComponentsregisterComponent, create-custom-component, attach-component
Systemscreate-custom-system, registerCustomSystem

Entities

Create an Entity

Entities represent objects in the scene. Use the createEntity() function to create a new entity.

let entity = createEntity()

Destroy an Entity

To remove an entity and its components from the scene, use destroyEntity.

destroyEntity(entityId: entity)

This ensures the entity is properly removed from all systems.


Parent-Child Relationships

To assign a parent to an entity, use the setParent function. This function establishes a hierarchical relationship between the specified entities.

// Create child and parent entities
let childEntity = createEntity()
let parentEntity = createEntity()

// Set parent-child relationship
setParent(childId: childEntity, parentId: parentEntity)

Find Entity

You can find an entity by name using the following function:

let ball = findEntity(name: "ball")

Transforms

Get Local Position

Retrieves the entity’s position relative to its parent.

let localPosition = getLocalPosition(entityId: entity)

Get World Position

Retrieves the entity’s absolute position in the scene.

let worldPosition = getPosition(entityId: entity)

Get Local Orientation

Retrieves the entity’s orientation matrix relative to its parent.

let localOrientation = getLocalOrientation(entityId: entity)

Get World Orientation

Retrieves the entity’s absolute orientation matrix.

let worldOrientation = getOrientation(entityId: entity)

Get Axis Vectors

Retrieve the entity’s forward, right, or up axis:

let forward = getForwardAxisVector(entityId: entity)
let right = getRightAxisVector(entityId: entity)
let up = getUpAxisVector(entityId: entity)

Translate the Entity

Move the entity to a new position:

translateTo(entityId: entity, position: simd_float3(5.0, 0.0, 3.0))

Move the entity by an offset relative to its current position:

translateBy(entityId: entity, position: simd_float3(1.0, 0.0, 0.0))

Rotate the Entity

Rotate the entity to a specific angle around an axis:

rotateTo(entityId: entity, angle: 45.0, axis: simd_float3(0.0, 1.0, 0.0))

Apply an incremental rotation to the entity:

rotateBy(entityId: entity, angle: 15.0, axis: simd_float3(0.0, 1.0, 0.0))

Directly set the entity’s rotation matrix:

rotateTo(entityId: entity, rotation: simd_float4x4( /* matrix values */ ))

Base path to assets

Define the asset directory the engine will use to load content (Assuming you are using an external folder during development). Please see Import-Export section for more details.

// Here we point it to a folder named "DemoGameAssets/Assets" on the Desktop.
// You can change this to any folder where you keep your own assets.
if let desktopURL = FileManager.default.urls(for: .desktopDirectory, in: .userDomainMask).first {
assetBasePath = desktopURL.appendingPathComponent("DemoGameAssets/Assets")
}

Rendering

To display a model, load its .usdc file and link it to the entity using setEntityMesh.

setEntityMesh(entityId: entity, filename: "entity", withExtension: "usdc")

Parameters:

  • entityId: The ID of the entity created earlier.
  • filename: The name of the .usdc file (without the extension).
  • withExtension: The file extension, typically "usdc".

Note: If PBR textures (e.g., albedo, normal, roughness, metallic maps) are included, the rendering system will automatically use the appropriate PBR shader to render the model with realistic lighting and material properties.

To display a Gaussian Splat model, load its .ply file and link it to the entity using setEntityGaussian.

setEntityGaussian(entityId: entity, filename: "splat", withExtension: "ply")

Parameters:

  • entityId: The ID of the entity created earlier.
  • filename: The name of the .ply file (without the extension).
  • withExtension: The file extension, typically "ply".

Note: The Gaussian System renders point cloud data stored in the .ply format. Ensure your Gaussian Splat file is properly formatted and contains the necessary attributes (position, color, opacity, scale, rotation).

Directional Light

Use for sunlight or distant key lights. Orientation (rotation) defines its direction.

let sun = createEntity()
createDirLight(entityId: sun)

Point Light

Omni light that radiates equally in all directions from a position.

let bulb = createEntity()
createPointLight(entityId: bulb)

Spot Light

Cone-shaped light with a position and direction.

let spot = createEntity()
createSpotLight(entityId: spot)

Area Light

Rect/area emitter used to mimic panels/windows; position and orientation matter.

let panel = createEntity()
createAreaLight(entityId: panel)

Animation

Load an Animation

Load the animation data for your model by providing the animation .usdc file and a name to reference the animation later.

setEntityAnimations(entityId: redPlayer, filename: "running", withExtension: "usdc", name: "running")

Set the Animation to play

Trigger the animation by referencing its name. This will set the animation to play on the entity.

changeAnimation(entityId: redPlayer, name: "running")

Pause the animation (Optional)

To pause the current animation, simply call the following function. The animation component will be paused for the current entity.

pauseAnimationComponent(entityId: redPlayer, isPaused: true)

Physics

Enable Physics on the Entity

Activate the physics simulation for your entity using the setEntityKinetics function. This function prepares the entity for movement and dynamic interaction.

setEntityKinetics(entityId: redPlayer)

Configure Physics Properties

You can customize the entity’s physics behavior by defining its mass and gravity scale:

  • Mass: Determines the force needed to move the object. Heavier objects require more force.
  • Gravity Scale: Controls how strongly gravity affects the entity (default is 0.0).
setMass(entityId: redPlayer, mass: 0.5)
setGravityScale(entityId: redPlayer, gravityScale: 1.0)

Apply Forces (Optional)

You can apply a custom force to the entity for dynamic movement. This is useful for simulating actions like jumps or pushes.

applyForce(entityId: redPlayer, force: simd_float3(0.0, 0.0, 5.0))

Note: Forces are applied per frame. To avoid unintended behavior, only apply forces when necessary.

Use the Steering System

For advanced movement behaviors, leverage the Steering System to steer entities toward or away from targets. This system automatically calculates the required forces.

Example: Steering Toward a Position

steerTo(entityId: redPlayer, targetPosition: simd_float3(0.0, 0.0, 5.0), maxSpeed: 2.0, deltaTime: deltaTime)

Additional Steering Functions

The Steering System includes other useful behaviors, such as:

  • steerAway()
  • steerPursuit()
  • followPath()

These functions simplify complex movement patterns, making them easy to implement.


Components

Register Components

Components define the behavior or attributes of an entity. Use registerComponent to add a component to an entity.

let entity = createEntity()

registerComponent(entityId: entity, componentType: RenderComponent.self)

Create Custom Component

Here’s an example of a simple custom component for a soccer player’s dribbling behavior:

public class DribblinComponent: Component {
public required init() {}
var maxSpeed: Float = 5.0
var kickSpeed: Float = 15.0
var direction: simd_float3 = .zero
}

⚠️ Note: Components should not include functions or game logic. Keep them as pure data containers.

Attaching a Component to an Entity

Once you’ve defined a component, you attach it to an entity in your scene:

let player = createEntity(name: "player")

// Attach DribblinComponent to the entity
registerComponent(entityId: player, componentType: DribblinComponent.self)

Systems

Create Custom System

If you’ve created a custom component, you’ll usually also want to create a custom system to make it do something.
Components store the data, but systems are where the behavior lives.

The engine automatically calls systems every frame.

Here’s a simple system that works with the DribblinComponent we defined earlier:

public func dribblingSystemUpdate(deltaTime: Float) {
// 1. Get the ID of the DribblinComponent
let customId = getComponentId(for: DribblinComponent.self)

// 2. Query all entities that have this component
let entities = queryEntitiesWithComponentIds([customId], in: scene)

// 3. Loop through each entity and update its data
for entity in entities {
guard let dribblingComponent = scene.get(component: DribblinComponent.self, for: entity) else {
continue
}

// Example logic: move player in the dribbling direction
dribblingComponent.direction = simd_normalize(dribblingComponent.direction)
let displacement = dribblingComponent.direction * dribblingComponent.maxSpeed * deltaTime

if let transform = scene.get(component: LocalTransformComponent.self, for: entity) {
transform.position += displacement
}
}
}

Registering the Custom System

All custom systems must be registered during initialization so the engine knows to run them every frame:

registerCustomSystem(dribblingSystemUpdate)